﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;

namespace Httlgd.DataCenter.Common.UserControls
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class AudioPlayerUserControl
    {
        #region Private members

        /// <summary>
        /// Indicate running time of the player
        /// </summary>
        private readonly DispatcherTimer _playerTimer = new DispatcherTimer();

        /// <summary>
        /// Start every time user make change on timeline
        /// </summary>
        private readonly DispatcherTimer _timelineChangedTimer = new DispatcherTimer();

        private MediaPlayer _audioPlayer;
        private bool _isPlaying;

        private bool _isTimelineChangedByUser = true;
        private bool _isVolChangedByUser = false;

        private double _volume = 0.5;
        public double Volume
        {
            get { return _volume; }
            set
            {
                if (value > 1 || value < 0)
                {
                    throw new Exception((string)FindResource("errorInvalidVolumeValue"));
                }

                _volume = value;

                if (!_isVolChangedByUser)
                    sldVolume.Value = _volume;

                UpdateVolumnToolTip();

                if (_audioPlayer != null)
                {
                    _audioPlayer.Volume = _volume;
                }
            }
        }

        #endregion

        #region Properties

        private string _resourcePath;
        public string ResoucePath
        {
            get { return _resourcePath; }
            set
            {
                _resourcePath = value;

                ResetPlayer();

                _audioPlayer = null;

                InitializePlayer();

                ToolTip = !String.IsNullOrEmpty(ResoucePath) ? ResoucePath.Replace("\\\\", "\\") : "Audio Player";
            }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// 
        /// </summary>
        public AudioPlayerUserControl()
        {
            InitializeComponent();

            sldVolume.Value = _volume;

            _playerTimer.Interval = new TimeSpan(0, 0, 0, 1);
            _playerTimer.Tick += PlayerTimer_Tick;

            _timelineChangedTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
            _timelineChangedTimer.Tick += TimelineChangedTimer_Tick;

            timeline.ValueChanged += TimelineValueChanged;
            sldVolume.ValueChanged += volume_ValueChanged;

            UpdateVolumnToolTip();
        }

        #endregion

        #region EventHandler

        private void btnPlayPause_Click(object sender, RoutedEventArgs e)
        {
            TogglePlayback();
        }

        private void audioPlayer_MediaOpened(object sender, EventArgs e)
        {
            if (_audioPlayer.NaturalDuration.HasTimeSpan)
            {
                timeline.Maximum = _audioPlayer.NaturalDuration.TimeSpan.TotalSeconds;

                _audioPlayer.Volume = sldVolume.Value;

                timeline.IsEnabled = true;
                btnPlayPause.IsEnabled = true;
                lblTime.Content = Helpers.SecondsToTimeFormat(_audioPlayer.NaturalDuration.TimeSpan.TotalSeconds);
            }
        }

        private void AudioPlayer_PlaybackEnded(object sender, EventArgs e)
        {
            ResetPlayer();
        }

        private void audioPlayer_MediaFailed(object sender, ExceptionEventArgs e)
        {
            throw e.ErrorException;
        }

        private void volume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            _isVolChangedByUser = true;

            if (_isVolChangedByUser)
                Volume = e.NewValue;

            _isVolChangedByUser = false;
        }

        private void TimelineValueChanged(object sender,
                                          RoutedPropertyChangedEventArgs<double> routedPropertyChangedEventArgs)
        {
            if (_isTimelineChangedByUser)
            {
                if (_timelineChangedTimer.IsEnabled)
                    _timelineChangedTimer.Stop();
                _timelineChangedTimer.Start();
            }

            _isTimelineChangedByUser = true;
        }

        #region Timer Tick

        private void TimelineChangedTimer_Tick(object sender, EventArgs e)
        {
            if (_audioPlayer == null) return;

            _audioPlayer.Position = Helpers.SecondToTimeSpan((int)timeline.Value);
            _timelineChangedTimer.Stop();
        }

        private void PlayerTimer_Tick(object sender, EventArgs e)
        {
            _isTimelineChangedByUser = false;
            if (!_timelineChangedTimer.IsEnabled)
            {
                timeline.Value = _audioPlayer.Position.TotalSeconds;
                lblTime.Content = Helpers.SecondsToTimeFormat(timeline.Value);
            }
        }

        #endregion

        #endregion

        #region Public Methods
        public void Play()
        {
            if (_audioPlayer == null) return;
            if (_isPlaying) return;

            //Play
            _audioPlayer.Play();
            _playerTimer.Start();

            _isPlaying = true;
            imgPlayPause.Source = (ImageSource)FindResource("ImagePause");
        }

        public void Stop()
        {
            if (_audioPlayer == null) return;

            ResetPlayer();
        }

        public void Pause()
        {
            if (_audioPlayer == null) return;
            if (!_isPlaying) return;

            //Stop, reset the player
            _audioPlayer.Pause();
            _playerTimer.Stop();

            _isPlaying = false;
            imgPlayPause.Source = (ImageSource)FindResource("ImagePlay");
        }
        #endregion

        #region Private methods

        private void InitializePlayer()
        {
            _isPlaying = false;
            _audioPlayer = new MediaPlayer();

            _audioPlayer.MediaEnded += AudioPlayer_PlaybackEnded;
            _audioPlayer.MediaOpened += audioPlayer_MediaOpened;
            _audioPlayer.MediaFailed += audioPlayer_MediaFailed;

            _audioPlayer.Open(new Uri(ResoucePath));
        }

        private void TogglePlayback()
        {
            if (_isPlaying)
            {
                Pause();
            }
            else
            {
                Play();
            }
        }

        private void ResetPlayer()
        {
            if (_audioPlayer != null)
            {
                _audioPlayer.Stop();
                _audioPlayer.Position = new TimeSpan(0);
            }

            _isTimelineChangedByUser = false;
            _playerTimer.Stop();
            _timelineChangedTimer.Stop();
            timeline.Value = 0;
            lblTime.Content = "00:00";

            _isPlaying = false;

            imgPlayPause.Source = (ImageSource)FindResource("ImagePlay");
        }

        private void UpdateVolumnToolTip()
        {
            sldVolume.ToolTip = Helpers.GetVolumnToolTip(_volume);
        }
        #endregion
    }
}